package com.rfid.reader;

import android.annotation.SuppressLint;
import android.util.Log;

import com.rfid.api.GFunction;
import com.rfid.basetype.UINT16;
import com.rfid.basetype.UINT8;
import com.rfid.spec.ISO15693TagDataReport;
import com.rfid.spec.L0_APL;
import com.rfid.spec.L0_IdentifyDataIso15693;
import com.rfid.spec.L0_PICC;
import com.rfid.spec.L0_PICC_HANDLE;
import com.rfid.spec.NetDataReport;
import com.rfid.spec.SpecAIPInvenParamISO15693;
import com.rfid.spec.SpecAirProtocInvenParam;
import com.rfid.spec.SpecConnectParams;
import com.rfid.spec.SpecInvenParamSet;
import com.rfid.spec.SpecTagAccess;
import com.rfid.spec.TagOperateHandle;
import com.rfid.spec.pc301.AN_PC301_APL_ISO15693;
import com.rfid.spec.pc301.AN_PC301_PICC_ICODESLI;
import com.rfid.spec.pc301.AN_PC301_PICC_ICODESLIX;
import com.rfid.spec.pc301.AN_PC301_PICC_ICODESLIX2;
import com.rfid.transport.BufferPack;
import com.rfid.transport.NdkSupport;
import com.rfid.transport.PCTransport;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Arrays;

public class DriverPC301 extends PCReader {
    public PCTransport m_transport;
    public BufferPack pbSnd;
    public BufferPack pbRecv;
    private byte[] mTranBuffer;
    private BufferPack mTranRecvBuf;
    private BufferPack pbInventoryRecv;
    private byte[] mInventoryRecvBuffer;
    public static final char MEM_OPT = '?';

    public DriverPC301() {
        this.m_transport = null;
        this.pbSnd = new BufferPack(512);
        this.pbRecv = new BufferPack(51200);
        this.mTranBuffer = new byte[51200];
        this.mTranRecvBuf = new BufferPack(51200);
        this.pbInventoryRecv = new BufferPack(51200);
        this.mInventoryRecvBuffer = new byte[1024];
        this.defaultInventoryTimeout = 1500;
        this.m_transport = new PCTransport();
    }

    public int RDR_GetCommType() {
        return this.m_transport.getCommType();
    }

    public int OpenBlueTooth(String addr) {
        return this.m_transport.connectBluetoolth(addr);
    }

    public int OpenCom(String sPath, int m_baud, String sFrame, byte addr) {
        return this.m_transport.connectCom(sPath, m_baud, sFrame, addr);
    }

    public int OpenNet(String remoteIp, int remotePort) {
        return this.m_transport.connectNetClent(remoteIp, remotePort);
    }

    public int OpenHid(String usbDes) {
        return this.m_transport.connectUsb(usbDes);
    }

    public int OpenZTEK(int port, int baud, String frame, byte addr) {
        return this.m_transport.connectZTEK(port, baud, frame, addr);
    }

    public int Close() {
        return this.m_transport.disConnect();
    }

    public int SetAcessAntenna(int AntennaID) {
        if (AntennaID == 1) return 0;
        return -3;
    }

    public int GetReaderInfor(StringBuffer buffer) {
        byte[] byVersion = new byte[2];
        byte[] byProductType = new byte[3];
        byte[] bySerialnum = new byte[5];
        int iret = CmdGetDeviceInfor(byVersion, byProductType, bySerialnum);
        if (iret != 0) return iret;
        String strFirmwareVersion = String.format("%02x.%02x", new Object[]{Byte.valueOf(byVersion[0]), Byte.valueOf(byVersion[1])});
        String strProductType = String.format("%02X%02X%02X", new Object[]{Byte.valueOf(byProductType[0]), Byte.valueOf(byProductType[1]), Byte.valueOf(byProductType[2])});
        String strSerial = String.format("%02X%02X%02X%02X%02X", new Object[]{Byte.valueOf(bySerialnum[0]), Byte.valueOf(bySerialnum[1]), Byte.valueOf(bySerialnum[2]), Byte.valueOf(bySerialnum[3]), Byte.valueOf(bySerialnum[4])});
        String strInfo = String.format("%s:%s:%s", new Object[]{strFirmwareVersion, strProductType, strSerial});
        buffer.append(strInfo);
        return 0;
    }

    @SuppressLint({"UseValueOf"})
    public int InventoryTransceive(BufferPack pbSnd, int mTimeout) {
        int iret = -1;
        this.pbInventoryRecv.flush();
        Arrays.fill(this.mInventoryRecvBuffer, (byte) 0);
        UINT16 resp_cmd = new UINT16();
        UINT8 resp_sta = new UINT8((byte) 0);
        int invenTimeout = mTimeout;
        if (invenTimeout <= 0) invenTimeout = this.defaultInventoryTimeout;
        this.m_LastReaderErrCode = 0;
        this.m_transport.ioctrol(1);
        this.pbInventoryRecv.flush();
        long curTime = System.currentTimeMillis();
        Log.d("S1", GFunction.encodeHexStr(this.pbSnd.GetBuffer(),this.pbSnd.getBufferLen()));
        iret = this.m_transport.send(pbSnd.GetBuffer(), pbSnd.getBufferLen(), 0);
        if (iret != 0) return iret;
        label47:
        while (true)
        {
            if (System.currentTimeMillis() - curTime >= invenTimeout) return -5;
            if (this.m_trancQuickExit)
            {
                this.m_trancQuickExit = false;
                return -35;
            }
            while (true)
            {
                Integer mReadLen = new Integer(this.mInventoryRecvBuffer.length);
                iret = this.m_transport.recv(this.mInventoryRecvBuffer, mReadLen, 0);
                if (iret > 0 || iret == -12) {
                    if (iret == -12) {
                        this.pbInventoryRecv.WriteData(this.mInventoryRecvBuffer, 0, mReadLen.intValue());
                        continue;
                    }
                    this.pbInventoryRecv.WriteData(this.mInventoryRecvBuffer, 0, iret);
                    continue label47;
                }
                break;
            }
            if (iret < 0) return iret;
            if (this.pbInventoryRecv.readable_length() >= 3) {
                this.pbInventoryRecv.ReadData(resp_cmd);
                this.pbInventoryRecv.ReadData(resp_sta);
                if (resp_cmd.getValue() != 510) continue;
                if (this.pbInventoryRecv.readable_length() > 0) {
                    if (this.pbInventoryRecv.readable_length() >= 9) {
                        byte dsfid = 0;
                        byte[] uid = new byte[8];
                        byte antid = 1;
                        long aip_type = 1L;
                        long picc_type = 0L;
                        dsfid = this.pbInventoryRecv.ReadData();
                        this.pbInventoryRecv.ReadData(uid, 8);
                        GFunction.BytesReverse(uid, 8);
                        if (this.pbInventoryRecv.readable_length() > 0)
                            antid = this.pbInventoryRecv.ReadData();
                        L0_IdentifyDataIso15693 idf_data = new L0_IdentifyDataIso15693();
                        System.arraycopy(uid, 0, idf_data.m_uid, 0, 8);
                        L0_APL paplISO15693 = this.m_L0RFID.GetAPL(1L);
                        if (paplISO15693 != null) picc_type = paplISO15693.IdentifyTag(idf_data);
                        String strUID = GFunction.encodeHexStr(uid);
                        ISO15693TagDataReport pTDR = ISO15693TagDataReport.create();
                        if (pTDR != null) {
                            pTDR.m_AIPType = aip_type;
                            pTDR.m_PICCType = picc_type;
                            pTDR.m_AntID = antid;
                            pTDR.m_Identifier = strUID;
                            pTDR.m_dsfid = dsfid;
                            System.arraycopy(uid, 0, pTDR.m_uid, 0, 8);
                            OnInventoryPICCFound(pTDR);
                        }
                    }
                    continue;
                }
                break;
            }
        }
        if (resp_sta.getValue() != 0) {
            if (resp_sta.getValue() != -32) {
                SetLastReaderErrCode(resp_sta.getValue());
                return -17;
            }
            return -21;
        }
        return 0;
    }


    private int CmdGetDeviceInfor(byte[] byVersion, byte[] byProductType, byte[] bySerialnum) {
        int iret = 0;
        this.m_syncLock.lock();
        this.pbSnd.flush();
        this.pbRecv.flush();
        char cmd=120;
        this.pbSnd.WriteData(cmd);
        iret = transceive(cmd, this.pbSnd, this.pbRecv, 500L, false);
        if (iret != 0) {
            this.m_syncLock.unlock();
            return iret;
        }
        if (this.pbRecv.readable_length() < 10) {
            iret = -12;
            this.m_syncLock.unlock();
            return iret;
        }
        this.pbRecv.ReadData(byVersion, 2);
        this.pbRecv.ReadData(byProductType, 3);
        this.pbRecv.ReadData(bySerialnum, 5);
        iret = 0;
        this.m_syncLock.unlock();
        return iret;
    }

    public int transceive(char reqCmd, BufferPack snd, BufferPack recv, long timeout, boolean waitEndPacket) {
        UINT16 resp_cmd = new UINT16();
        UINT8 resp_sta = new UINT8();
        this.mTranRecvBuf.flush();
        Arrays.fill(this.mTranBuffer, (byte) 0);
        this.m_LastReaderErrCode = 0;
        this.m_transport.ioctrol(1);
        int iret = this.m_transport.send(snd.GetBuffer(), snd.getBufferLen(), 0);
        if (iret != 0) return iret;
        long curTime = System.currentTimeMillis();
        label33:
        while (true) {
            if (System.currentTimeMillis() - curTime > timeout) return -5;
              /*
            雷做了修改了，当接收到数据时不清空缓存
             */
            //this.mTranRecvBuf.flush();
            if (this.mTranRecvBuf.getBufferLen() <= 0) {
                this.mTranRecvBuf.flush();
            }
            while (true) {
                iret = this.m_transport.recv(this.mTranBuffer, Integer.valueOf(this.mTranBuffer.length), 0);
                if (iret > 0 || iret == -12) {
                    if (iret == -12) {
                        this.mTranRecvBuf.WriteData(this.mTranBuffer, 0, this.mTranBuffer.length);
                        continue;
                    }
                    this.mTranRecvBuf.WriteData(this.mTranBuffer, 0, iret);
                    continue label33;
                }
                break;
            }
            if (iret < 0) return iret;
            if (this.mTranRecvBuf.readable_length() >= 3) {
                this.mTranRecvBuf.ReadData(resp_cmd);
                this.mTranRecvBuf.ReadData(resp_sta);
                if (resp_cmd.getValue() != reqCmd) continue;
                recv.WriteData(this.mTranRecvBuf.GetBuffer(), 3, this.mTranRecvBuf.getBufferLen() - 3);
                if (waitEndPacket && this.mTranRecvBuf.readable_length() > 0) continue;
                break;
            }
        }
        if (resp_sta.getValue() != 0) {
            SetLastReaderErrCode(resp_sta.getValue());
            return -17;
        }
        return 0;
    }

    int AirProtocolLayerInit() {
        AN_PC301_APL_ISO15693 aplIso15693 = AN_PC301_APL_ISO15693.create();
        if (aplIso15693 != null) {
            aplIso15693.m_reader = this;
            AN_PC301_PICC_ICODESLI icodesli = AN_PC301_PICC_ICODESLI.create();
            if (icodesli != null) {
                icodesli.m_apl = aplIso15693;
                icodesli.m_reader = this;
                aplIso15693.RegisterPicc(icodesli);
            }
            AN_PC301_PICC_ICODESLIX icodeslix = AN_PC301_PICC_ICODESLIX.create();
            if (icodeslix != null) {
                icodeslix.m_apl = aplIso15693;
                icodeslix.m_reader = this;
                aplIso15693.RegisterPicc(icodeslix);
            }
            AN_PC301_PICC_ICODESLIX2 icodeslix2 = AN_PC301_PICC_ICODESLIX2.create();
            if (icodeslix2 != null) {
                icodeslix2.m_apl = aplIso15693;
                icodeslix2.m_reader = this;
                aplIso15693.RegisterPicc(icodeslix2);
            }
            this.m_L0RFID.RegisterAPL(aplIso15693);
        }
        return 0;
    }

    void SetLastReaderErrCode(int error) {
        this.m_LastReaderErrCode = error;
    }

    int LowLevelInit() {
        SpecAIPInvenParamISO15693 iso15693param = SpecAIPInvenParamISO15693.create();
        if (iso15693param != null) {
            iso15693param.m_aipType = 1L;
            iso15693param.m_antID = 0L;
            iso15693param.m_enableAFI = false;
            iso15693param.m_AFI = 0;
            iso15693param.m_slotType = 0;
            this.m_DefInvenParams.AddAirProtocol(iso15693param);
        }
        return 0;
    }

    public int PICC_Inventory(byte AIType, byte[] AntennaIDs, int mTimeout, SpecInvenParamSet InvenParams) {
        int iret = 0;
        SpecInvenParamSet pInvenParams = InvenParams;
        if (pInvenParams == null) pInvenParams = this.m_DefInvenParams;
        SpecAirProtocInvenParam p = pInvenParams.m_AirProtocolParams;
        while (p != null) {
            L0_APL apl = this.m_L0RFID.GetAPL(p.m_aipType);
            if (apl != null) {
                iret = apl.Inventory(AIType, mTimeout, p, pInvenParams);
                if (iret != 0) return iret;
            }
            p = (SpecAirProtocInvenParam) p.m_next;
        }
        return iret;
    }

    public int PICC_Connect(SpecConnectParams Params, TagOperateHandle retPICCHandle) {
        int iret = -1;
        if (Params == null) return -3;
        L0_APL apl = this.m_L0RFID.GetAPL(Params.m_AIPId);
        if (apl == null) return -7;
        L0_PICC picc = apl.GetPicc(Params.m_TagId);
        if (picc == null) return -7;
        iret = picc.Connect(Params, retPICCHandle);
        if (iret != 0) return iret;
        this.m_lastConnectTagTypeStore = Params.m_TagId;
        if (retPICCHandle.getTagHandle() == null) return -6;
        this.m_ConnPICCs.Register(retPICCHandle.getTagHandle());
        (retPICCHandle.getTagHandle()).m_reader = this;
        return 0;
    }

    public int OpenRFTransmitter(byte mAntId) {
        if (mAntId == 1) return OpenRFTransmitter();
        return 0;
    }

    public int OpenRFTransmitter() {
        return SetSta_RF((byte) 1);
    }

    public int CloseRFTransmitter() {
        return SetSta_RF((byte) 0);
    }

    private int SetSta_RF(byte OnOff) {
        int iret = 0;
        this.m_syncLock.lock();
        this.pbSnd.flush();
        this.pbRecv.flush();
        char cmd = 377;
        this.pbSnd.WriteData(cmd);
        this.pbSnd.WriteData(OnOff);
        iret = transceive(cmd, this.pbSnd, this.pbRecv, 500L, false);
        if (iret != 0) {
            this.m_syncLock.unlock();
            return iret;
        }
        iret = 0;
        this.m_syncLock.unlock();
        return iret;
    }

    public String GetDeviceName() {
        return "PC301";
    }

    public int WriteCfgBlock(int cfgNo, byte[] cfgdata) {
        this.m_syncLock.lock();
        this.pbSnd.flush();
        this.pbRecv.flush();
        char cmd = 421;
        this.pbSnd.WriteData(cmd);
        this.pbSnd.WriteData((byte) (cfgNo & 0xFF));
        this.pbSnd.WriteData(cfgdata, 0, 8);
        int iret = transceive(cmd, this.pbSnd, this.pbRecv, 500L, false);
        if (iret != 0) {
            this.m_syncLock.unlock();
            return iret;
        }
        this.m_syncLock.unlock();
        return 0;
    }

    public int WriteConfigBlock(int cfgno, byte[] cfgdata, int nSize, int mask) {
        byte[] cfgblock = new byte[8];
        int nCopy = 8;
        if (nSize < nCopy) nCopy = nSize;
        System.arraycopy(cfgdata, 0, cfgblock, 0, nCopy);
        return WriteCfgBlock(cfgno, cfgblock);
    }

    public int SaveConfigBlock(int cfgno) {
        this.m_syncLock.lock();
        this.pbSnd.flush();
        this.pbRecv.flush();
        char cmd = 677;
        this.pbSnd.WriteData(cmd);
        this.pbSnd.WriteData(cfgno);
        int iret = transceive(cmd, this.pbSnd, this.pbRecv, 500L, false);
        if (iret != 0) {
            this.m_syncLock.unlock();
            return iret;
        }
        this.m_syncLock.unlock();
        return 0;
    }

    public int ReadCfgBlock(int cfgNo, byte[] cfgdata) {
        if (cfgdata.length < 8) return -12;
        this.m_syncLock.lock();
        this.pbSnd.flush();
        this.pbRecv.flush();
        char cmd = 165;
        this.pbSnd.WriteData(cmd);
        this.pbSnd.WriteData((byte) (cfgNo & 0xFF));
        int iret = transceive(cmd, this.pbSnd, this.pbRecv, 500L, false);
        if (iret != 0) {
            this.m_syncLock.unlock();
            return iret;
        }
        if (this.pbRecv.readable_length() < 8) {
            iret = -12;
            this.m_syncLock.unlock();
            return iret;
        }
        this.pbRecv.ReadData(cfgdata, 8);
        iret = 0;
        this.m_syncLock.unlock();
        return iret;
    }

    public int GetRFPower(Byte index) {
        byte[] cfgdata = new byte[8];
        int iret = ReadCfgBlock(1, cfgdata);
        if (iret != 0) return (byte) (iret & 0xFF);
        if (cfgdata[0] >= 1 && cfgdata[0] <= 6) {
            NdkSupport.SetByteValue(index, cfgdata[0]);
            return 0;
        }
        return 1;
    }

    public int SetRFPower(byte index) {
        byte[] buffer = new byte[8];
        int iret = ReadCfgBlock(1, buffer);
        if (iret != 0) return iret;
        buffer[0] = index;
        iret = WriteCfgBlock(1, buffer);
        if (iret != 0) return iret;
        iret = SaveConfigBlock(1);
        if (iret != 0) return iret;
        return 0;
    }

    public int LoadFactoryDefault() {
        int iret = 0;
        this.m_syncLock.lock();
        this.pbSnd.flush();
        this.pbRecv.flush();
        char cmd = 384;
        this.pbSnd.WriteData(cmd);
        iret = transceive(cmd, this.pbSnd, this.pbRecv, 500L, false);
        if (iret != 0) {
            this.m_syncLock.unlock();
            return iret;
        }
        iret = 0;
        this.m_syncLock.unlock();
        return iret;
    }

    public int PICC_Access(L0_PICC_HANDLE hPICC, SpecTagAccess tagAccess) {
        if (hPICC == null) return -3;
        if (!this.m_ConnPICCs.Find(hPICC)) return -7;
        if (hPICC.m_picc == null) return -1;
        return ((L0_PICC) hPICC.m_picc).Access(hPICC, tagAccess);
    }

    public int OnlineCheck() {
        byte[] byVersion = new byte[2];
        byte[] byProductType = new byte[3];
        byte[] bySerialnum = new byte[5];
        int iret = CmdGetDeviceInfor(byVersion, byProductType, bySerialnum);
        this.m_firmVer = (byVersion[1] & 0xFF | byVersion[0] << 8 & 0xFF00);
        this.m_productType = (byProductType[0] << 16 & 0xFF0000 | byProductType[1] << 8 & 0xFF00 | byProductType[2] & 0xFF);
        return iret;
    }

    public int GetOverflowTime(Integer mTime) {
        byte[] cfgdata = new byte[8];
        int iret = ReadCfgBlock(3, cfgdata);
        if (iret != 0) return iret;
        int val = cfgdata[2];
        if (val < 0) val += 256;
        NdkSupport.SetIntegerValue(mTime, val);
        return 0;
    }

    public int SetOverflowTime(int mTime) {
        byte[] buffer = new byte[8];
        int iret = ReadCfgBlock(3, buffer);
        if (iret != 0) return iret;
        buffer[2] = (byte) (mTime & 0xFF);
        iret = WriteCfgBlock(3, buffer);
        if (iret != 0) return iret;
        iret = SaveConfigBlock(3);
        if (iret != 0) return iret;
        return 0;
    }

    public int Login(byte[] pwd) {
        if (pwd.length != 8) return -3;
        int iret = 0;
        this.m_syncLock.lock();
        this.pbSnd.flush();
        this.pbRecv.flush();
        this.pbSnd.WriteData('?');
        this.pbSnd.WriteData(pwd, 0, 8);
        iret = transceive('?', this.pbSnd, this.pbRecv, 1000L, false);
        if (iret != 0) {
            this.m_syncLock.unlock();
            return iret;
        }
        iret = 0;
        this.m_syncLock.unlock();
        return iret;
    }

    public int EnablePasswordLogin(byte[] pwd, boolean enable) {
        if (pwd.length != 8) return -3;
        int iret = 0;
        byte en = (byte) (enable ? 1 : 0);
        this.m_syncLock.lock();
        this.pbSnd.flush();
        this.pbRecv.flush();
        this.pbSnd.WriteData('?');
        this.pbSnd.WriteData(pwd, 0, 8);
        this.pbSnd.WriteData(en);
        iret = transceive('?', this.pbSnd, this.pbRecv, 1000L, false);
        if (iret != 0) {
            this.m_syncLock.unlock();
            return iret;
        }
        iret = 0;
        this.m_syncLock.unlock();
        return iret;
    }

    public int UpdateLoginPassword(byte[] pwd, byte[] newPwd) {
        if (pwd.length != 8 || newPwd.length != 8) return -3;
        int iret = 0;
        this.m_syncLock.lock();
        this.pbSnd.flush();
        this.pbRecv.flush();
        this.pbSnd.WriteData('?');
        this.pbSnd.WriteData(pwd, 0, 8);
        this.pbSnd.WriteData(newPwd, 0, 8);
        this.pbSnd.WriteData(null, 0, 8);
        iret = transceive('?', this.pbSnd, this.pbRecv, 1000L, false);
        if (iret != 0) {
            this.m_syncLock.unlock();
            return iret;
        }
        iret = 0;
        this.m_syncLock.unlock();
        return iret;
    }

    public int checkTags(int[] ANT, byte[][] SN_DATA, boolean[] ret) {
        if (ANT.length <= 0) {
            Log.d("freezer_test", "ANT.length <= 0");
            return -3;
        }
        if (ret.length != ANT.length) {
            Log.d("freezer_test", "ret.length != ANT.length");
            return -3;
        }
        for (int i = 0; i < ret.length; i++) ret[i] = false;
        int iret = 0;
        this.m_syncLock.lock();
        this.pbSnd.flush();
        this.pbRecv.flush();
        this.pbSnd.WriteData('?');
        byte TAG_C = (byte) ANT.length;
        this.pbSnd.WriteData(TAG_C);
        for (int i = 0; i < ANT.length; i++) {
            byte FLAG = 1;
            this.pbSnd.WriteData(FLAG);
            byte ACNT = 0;
            for (int j = 31; j >= 0; j--)
                if ((ANT[i] >> j & 0x01) == 1) {
                    ACNT = (byte) j;
                    break;
                }
            this.pbSnd.WriteData(ACNT);
            byte[] ASEL = new byte[2];
            ASEL[0] = (byte) (ANT[i] & 0xFF);
            ASEL[1] = (byte) (ANT[i] >> 8 & 0xFF);
            this.pbSnd.WriteData(ASEL, 0, 2);
            this.pbSnd.WriteData((byte) 8);
            this.pbSnd.WriteData(SN_DATA[i], 0, SN_DATA[i].length);
        }
        iret = transceive('?', this.pbSnd, this.pbRecv, 3000L, false);
        if (iret != 0) {
            this.m_syncLock.unlock();
            return iret;
        }
        byte[] buf = this.pbRecv.GetBuffer();
        int TAG_RC = buf[0];
        if (TAG_RC > 0) {
            int offt = 1;
            for (int i = 0; i < TAG_RC; i++) {
                if (buf[offt + 1] == 0) ret[buf[offt]] = false;
                else if (buf[offt + 1] == 1) ret[buf[offt]] = true;
                offt += 2;
            }
        }
        iret = 0;
        this.m_syncLock.unlock();
        return iret;
    }

    public int DetectTags(int[] ant, byte[][] uid, boolean[] ret) {
        int offt = 0;
        int iret = 0;
        for (offt = 0; offt < ant.length; offt += 16) {
            int size = ant.length - offt;
            if (size >= 16) size = 16;
            byte[][] _SN_DATA = new byte[size][uid[0].length];
            int[] _ANT = new int[size];
            boolean[] _ret = new boolean[size];
            for (int i = 0; i < size; i++) {
                _ANT[i] = ant[i + offt];
                for (int n = 0; n < uid[0].length; n++)
                    _SN_DATA[i][n] = uid[i + offt][uid[0].length - 1 - n];
                _ANT[i] = ant[i + offt];
            }
            iret = checkTags(_ANT, _SN_DATA, _ret);
            if (iret == 0) for (int i = 0; i < size; i++) ret[i + offt] = _ret[i];
            else return iret;
            if (iret != 0) break;
        }
        return iret;
    }

    public int CmdNoiseDetection(byte[] noisebuf, int[] bufSize) {
        int iret = 0;
        this.m_syncLock.lock();
        byte option = 0;
        int idx = 0;
        int nSize = 0;
        int datalen = 0;
        nSize = bufSize[0];
        iret = 0;
        do {
            this.pbSnd.flush();
            this.pbRecv.flush();
            this.pbSnd.WriteData('?');
            this.pbSnd.WriteData(option);
            iret = transceive('?', this.pbSnd, this.pbRecv, 3000L, false);
            if (iret != 0) {
                this.m_syncLock.unlock();
                return iret;
            }
            if (this.pbRecv.readable_length() < 2) {
                iret = -12;
                this.m_syncLock.unlock();
                return iret;
            }
            option = this.pbRecv.ReadData();
            datalen = this.pbRecv.ReadData();
            if (datalen < 0) datalen += 256;
            if (this.pbRecv.readable_length() < datalen) {
                iret = -12;
                this.m_syncLock.unlock();
                return iret;
            }
            int bytesToRead = datalen;
            if (nSize < bytesToRead) bytesToRead = nSize;
            byte[] noiseBuffer = new byte[bytesToRead];
            this.pbRecv.ReadData(noiseBuffer, bytesToRead);
            System.arraycopy(noiseBuffer, 0, noisebuf, idx, bytesToRead);
            idx += bytesToRead;
            nSize -= bytesToRead;
        } while (nSize > 0 && option != 0);
        bufSize[0] = idx;
        iret = 0;
        this.m_syncLock.unlock();
        return iret;
    }

    public int DetectNoise(int[] voltage, int[] dataSize) {
        int[] bufferSize = {dataSize[0] * 2};
        byte[] bufferData = new byte[bufferSize[0]];
        int iret = CmdNoiseDetection(bufferData, bufferSize);
        if (iret != 0) return iret;
        if (dataSize[0] % 2 != 0) return -27;
        dataSize[0] = bufferSize[0] / 2;
        for (int i = 0; i < dataSize[0]; i++) {
            int b0 = bufferData[2 * i];
            int b1 = bufferData[2 * i + 1];
            if (b0 < 0) b0 += 256;
            if (b1 < 0) b1 += 256;
            voltage[i] = b0 + b1 * 256;
            voltage[i] = (int) (voltage[i] * 3.22265625D);
        }
        return 0;
    }

    public int GetNoiseLevel(byte AntennaID, int[] min, int[] avg, int[] max) {
        int iret = 0;
        if (GetAntennaInterfaceCount() > 0) {
            iret = SetAcessAntenna(AntennaID);
            if (iret != 0) return iret;
        }
        int[] voltage = new int[2048];
        int[] dataSize = {voltage.length};
        iret = DetectNoise(voltage, dataSize);
        if (iret != 0) return iret;
        min[0] = 0;
        max[0] = 0;
        int m_total = 0;
        for (int i = 0; i < dataSize[0]; i++) {
            m_total += voltage[i];
            if (max[0] < voltage[i]) max[0] = voltage[i];
        }
        avg[0] = m_total / dataSize[0];
        return -4;
    }

    public boolean IsSupportNoiseDetect() {
        return true;
    }

    /*
   网络搜索
    */
    public int Net_Inventory() {
        this.m_syncLock.lock();
        this.pbSnd.flush();
        this.pbRecv.flush();
        char cmd = 459;
        this.pbSnd.WriteData(cmd);
        int iret = InventoryNetTransceive(this.pbSnd,1000);
        if (iret != 0) {
            this.m_syncLock.unlock();
            return iret;
        }
        this.m_syncLock.unlock();
        return iret;
    }
    public int InventoryNetTransceive(BufferPack pbSnd, int mTimeout)
    {

        int iret=-1;
        UINT16 resp_cmd = new UINT16();
        UINT8 resp_sta = new UINT8((byte) 0);
        this.pbInventoryRecv.flush();
        try {
            byte[] cmd =new  byte[] {(byte)0xAA,0x06,(byte)0xFF,(byte)0xCB,0x01,(byte)0x90,(byte)0xB1};
            client = new DatagramSocket();
            client.setSoTimeout(mTimeout);
            sPacket =new DatagramPacket(cmd,cmd.length, InetAddress.getByName("255.255.255.255"),6688);
            String hex1=GFunction.encodeHexStr(cmd,cmd.length);
            Log.d("PCTransport", "SS: "+hex1);
            client.send(sPacket);
            while (true)
            {
                this.pbInventoryRecv.flush();
                try
                {
                    byte[] rev=new byte[1024];
                    DatagramPacket  rPacket = new DatagramPacket(rev,rev.length);
                    client.receive(rPacket);
                    byte[] buffer= rPacket.getData();
                    int len=rPacket.getLength();
                    String hex=GFunction.encodeHexStr(buffer,len);
                    Log.d("PCTransport", "RR: "+hex);
                    this.pbInventoryRecv.WriteData(buffer, 3, len-5);
                    if (this.pbInventoryRecv.readable_length() >= 3) {
                        this.pbInventoryRecv.ReadData(resp_cmd);
                        this.pbInventoryRecv.ReadData(resp_sta);
                        if (this.pbInventoryRecv.readable_length() > 0) {
                            if (this.pbInventoryRecv.readable_length() >= 18) {
                                byte[] pIp=new byte[4];
                                byte[] pMask=new byte[4];
                                byte[] pGrateway=new byte[4];
                                byte[] pMac=new byte[6];
                                this.pbInventoryRecv.ReadData(pIp, 4);
                                this.pbInventoryRecv.ReadData(pMask, 4);
                                this.pbInventoryRecv.ReadData(pGrateway, 4);
                                this.pbInventoryRecv.ReadData(pMac, 4);
                                String strIp = String.format("%d.%d.%d.%d", new Object[]{pIp[0] &0xFF, pIp[1] &0xFF, pIp[2] &0xFF, pIp[3] &0xFF});
                                String strMask = String.format("%d.%d.%d.%d", new Object[]{pMask[0] & 0xFF, pMask[1] & 0xFF, pMask[2] & 0xFF, pMask[3] & 0xFF});
                                String strGrateway = String.format("%d.%d.%d.%d", new Object[]{pGrateway[0] &0xFF, pGrateway[1] &0xFF,pGrateway[2] &0xFF, pGrateway[3] &0xFF});
                                String strMac = String.format("%02x-%02x-%02x-%02x-%02x", new Object[]{Byte.valueOf(pMac[0]), Byte.valueOf(pMac[1]), Byte.valueOf(pMac[2]), Byte.valueOf(pMac[3]),Byte.valueOf(pMac[4]),Byte.valueOf(pMac[5])});
                                NetDataReport pTDR = NetDataReport.create();
                                if (pTDR != null) {
                                    pTDR.m_Ip = strIp;
                                    pTDR.m_Mask = strMask;
                                    pTDR.m_Grateway = strGrateway;
                                    pTDR.m_Mac = strMac;
                                    OnInventoryNetFound(pTDR);
                                }
                            }
                        }
                    }

                }
                catch (Exception ex )
                {
                    //  ex.printStackTrace();
                    break;
                }
            }
            client.close();
            OnInventoryNetFinish();

        }
        catch (Exception ex)
        {

        }
        return 0;
    }
    //设置网络
    public  int SetNet(byte[] pIp,byte[] pMask,byte[] pGrateway)
    {
        this.m_syncLock.lock();
        this.pbSnd.flush();
        this.pbRecv.flush();
        char cmd = 715;
        this.pbSnd.WriteData(cmd);
        this.pbSnd.WriteData(pIp,0,4);
        this.pbSnd.WriteData(pMask,0,4);
        this.pbSnd.WriteData(pGrateway,0,4);
        int iret = Upd_Transceive(pIp,cmd, this.pbSnd, this.pbRecv, 500L, false);
        if (iret != 0) {
            this.m_syncLock.unlock();
            return iret;
        }
        this.m_syncLock.unlock();
        return 0;
    }
    private char crc16(byte[] pCrcData, int offset, int pLen)
    {
        int CRC = 61166;
        if (pLen==0)
        {
            return Character.MIN_VALUE;
        }
        for (int i = 0; i < pLen; i++) {
            CRC ^= pCrcData[i + offset]&0xFF;
            for (int j=0;j<8;j++)
            {
                if ((CRC &0x0001)!=0)
                {
                    CRC=(CRC>>1)^0x8408;
                }else {
                    CRC=(CRC>>1);
                }
            }
        }
        return  (char)CRC;
    }
    private BufferPack llSendframe = new BufferPack();
    private BufferPack pllRecvFrame = new BufferPack();
    private int Udp_send(byte[] buffer, int offset, int m_Size) {
        this.llSendframe.flush();
        //包头
        this.llSendframe.WriteData("AA");
        //长度
        this.llSendframe.WriteData((byte)(4 + m_Size));
        //地址
        this.llSendframe.WriteData("FF");
        //数据=命令码+数据内容
        this.llSendframe.WriteData(buffer, offset, m_Size);
        char crc16 = crc16(this.llSendframe.GetBuffer(), 1, this.llSendframe.getBufferLen() - 1);
        this.llSendframe.WriteData(crc16);
        return 0;
    }
    public int Upd_Transceive(byte[] pIp, char reqCmd, BufferPack snd, BufferPack recv, long timeout, boolean waitEndPacket) {
        int iret=-1;
        UINT16 resp_cmd = new UINT16();
        UINT8 resp_sta = new UINT8((byte) 0);
        String strIp = String.format("%d.%d.%d.%d", new Object[]{pIp[0] &0xFF, pIp[1] &0xFF, pIp[2] &0xFF, pIp[3] &0xFF});
        try {
            if (client !=null && !client.isClosed())
            {
                client.close();
            }
            client = new DatagramSocket();
            client.setSoTimeout((int) timeout);
            Udp_send(snd.GetBuffer(),0,snd.getBufferLen());
            sPacket =new DatagramPacket(llSendframe.GetBuffer(),llSendframe.getBufferLen(), InetAddress.getByName("255.255.255.255"),6688);
            String hex1=GFunction.encodeHexStr(llSendframe.GetBuffer(),llSendframe.getBufferLen());
            Log.d("PCTransport", "SS: "+hex1);
            client.send(sPacket);
            try {
                pllRecvFrame.flush();
                byte[] rev=new byte[1024];
                DatagramPacket  rPacket = new DatagramPacket(rev,rev.length);
                client.receive(rPacket);
                byte[] buffer= rPacket.getData();
                int len=rPacket.getLength();
                String hex=GFunction.encodeHexStr(buffer,len);
                Log.d("PCTransport", "RR: "+hex);
                pllRecvFrame.WriteData(buffer, 3, len-5);
                if (this.pllRecvFrame.readable_length() >= 3) {
                    this.pllRecvFrame.ReadData(resp_cmd);
                    this.pllRecvFrame.ReadData(resp_sta);
                    if (resp_cmd.getValue() != reqCmd) return  iret ;
                    iret=0;
                }
            }catch (Exception ex)
            {
                ex.printStackTrace();
            }

        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }

        return iret;
    }
}
